package com.bankcomm.luafuction;

import org.keplerproject.luajava.LuaException;
import org.keplerproject.luajava.LuaObject;
import org.keplerproject.luajava.LuaState;

import android.R.integer;
import android.content.pm.PackageManager;
import android.os.SystemClock;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;

import com.bankcomm.common.ConfigManager;
import com.rytong.tools.ui.Component;
import com.rytong.tools.utils.Utils;

public class LuaGesture {
	// 控件或布局手势
	private GestureDetector mGD_;
	// 控件或布局缩放手势
	private ScaleGestureDetector mSGD_;
	// 控件或布局缩放手势监听事件
	private LuaObject scaleListener_;
	// 控件或布局拖动手势监听事件
	private LuaObject dragListener_;
	// 控件或布局滑动手势监听事件
	private LuaObject swipeListener_;
	// 控件或布局旋转手势事件
	private LuaObject rotationListen_;
	// 控件或布局点击手势监听事件
	private LuaObject tapListener_;
	// 控件或布局长按手势监听事件
	private LuaObject longTapListener_;
	//　原来的旋转角度
	private float oldrotation;
	//降低灵敏度
	int istrac = 0;
	// 是否支持多点触摸（至少两点）。
	private boolean isSupportMultiTouch_;

	public LuaGesture() {
		mGD_ = new GestureDetector(ConfigManager.currentView_,
				new SimpleOnGestureListener());
		mSGD_ = new ScaleGestureDetector(ConfigManager.currentView_,
				new ScaleGestureListener());
		isSupportMultiTouch_ = isSupportMultiTouch();
		try {
			Component.LUASTATE.pushObjectValue(this);
			Component.LUASTATE.setGlobal("luagesture");
			final String luahead = "gesture = {};";
			final String luafc1 = "function gesture:setScaleListener(control, listener) luagesture:setScaleListener(control, listener); end;";
			final String luafc2 = "function gesture:setDragListener(control, listener) luagesture:setDragListener(control,listener); end;";
			final String luafc3 = "function gesture:setSwipeListener(control, listener) luagesture:setSwipeListener(control, listener); end;";
			final String luafc4 = "function gesture:setRotationListener(control, listener) luagesture:setRotationListener(control, listener); end;";
			final String luafc5 = "function gesture:setTapListener(control, listener) luagesture:setTapListener(control, listener); end;";
			final String luafc6 = "function gesture:setLongTapListener(control, listener) luagesture:setLongTapListener(control, listener); end;";
			Component.LUASTATE.gc(LuaState.LUA_GCCOLLECT, 0);
			int index = Component.LUASTATE.LdoString(luahead.concat(luafc1)
					.concat(luafc2).concat(luafc3).concat(luafc4)
					.concat(luafc5).concat(luafc6));
			if (index > 0) {
				Utils.printOutToConsole("Lua Text has some errors:");
				Utils.printOutToConsole(Component.LUASTATE.LcheckString(-1));
			}
		} catch (LuaException e) {
			Utils.printException(e);
		}
	}

	/**
	 * 为视图设置缩放方法
	 * 
	 * @param control
	 *            控件或布局
	 * @param listener
	 *            监听方法
	 */
	public void setScaleListener(final Component control, Object listener) {
		if (listener instanceof LuaObject) {
			scaleListener_ = (LuaObject) listener;
		}
		oldrotation = 0;
		setRotation(control);
	}

	/**
	 * 为视图设置拖动(慢速移动)监听方法
	 * 
	 * @param control
	 *            控件或布局
	 * @param listener
	 *            监听方法
	 */
	public void setDragListener(Component control, Object listener) {
		if (listener instanceof LuaObject) {
			dragListener_ = (LuaObject) listener;
		}
		setViewListener(control, mGD_);
	}

	/**
	 * 为视图设置移动(快速移动)监听方法
	 * 
	 * @param control
	 *            控件或布局
	 * @param listener
	 *            监听方法
	 */
	public void setSwipeListener(Component control, Object listener) {
		if (listener instanceof LuaObject) {
			swipeListener_ = (LuaObject) listener;
		}
		setViewListener(control, mGD_);
	}

	/**
	 * 为视图设置当前旋转的弧度值监听方法
	 * 
	 * @param control
	 *            控件或布局
	 * @param listener
	 *            监听方法
	 */
	public void setRotationListener(Component control, Object listener) {
		if (listener instanceof LuaObject) {
			rotationListen_ = (LuaObject) listener;
		}
		setViewListener(control, mGD_);
	}

	/**
	 * 为视图设置点击监听方法
	 * 
	 * @param control
	 *            控件或布局
	 * @param listener
	 *            监听方法
	 */
	public void setTapListener(Component control, Object listener) {
		if (listener instanceof LuaObject) {
			tapListener_ = (LuaObject) listener;
		}
		setViewListener(control, mGD_);
	}

	/**
	 * 为视图设置长按监听方法
	 * 
	 * @param control
	 *            控件或布局
	 * @param listener
	 *            监听方法
	 */
	public void setLongTapListener(Component control, Object listener) {
		if (listener instanceof LuaObject) {
			longTapListener_ = (LuaObject) listener;
		}
		setViewListener(control, mGD_);
	}

	/**
	 * 为视图设置监听事件
	 * 
	 * @param c
	 *            控件或布局
	 * @param gestureDetector
	 *            手势
	 */
	private void setViewListener(Component c, final Object gestureDetector) {
		if (c == null || gestureDetector == null)
			return;
		if (gestureDetector instanceof GestureDetector) {
			c.realView_.setOnTouchListener(new View.OnTouchListener() {

				@Override
				public boolean onTouch(View v, MotionEvent event) { 
					return ((GestureDetector) gestureDetector)
							.onTouchEvent(event);
				}
			});

		} else if (gestureDetector instanceof ScaleGestureDetector) {
			c.realView_.setOnTouchListener(new View.OnTouchListener() {

				@Override
				public boolean onTouch(View v, MotionEvent event) {
					return ((ScaleGestureDetector) gestureDetector)
							.onTouchEvent(event);
				}
			});
		}
		// 遍历他的所有子控件，为其设置监听
		if (c.realView_ instanceof ViewGroup) {
			int size = ((ViewGroup) (c.realView_)).getChildCount();
			for (int i = 0; i < size; i++) {
				setViewListener(c.getComponent(((ViewGroup) (c.realView_))
						.getChildAt(i)), gestureDetector);
			}
		}
	}
	
	/**
	 * 为视图设置监听事件
	 * 
	 * @param c
	 *            控件或布局
	 * @param gestureDetector
	 *            手势
	 */
	private void setRotation(Component c) {
		if (c == null)
			return;
		c.realView_.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) { 
				if(isSupportMultiTouch_){ // 支持多点触摸。
					switch (event.getAction() & MotionEvent.ACTION_MASK) {
					case MotionEvent.ACTION_POINTER_DOWN: // 当第二个手指按下的时候触发这个事件。
						if (rotationListen_ != null) {
							oldrotation = getViewRotation(event.getX(0), event.getY(0), event.getX(1),
									event.getY(1));
						}
						break;
					case MotionEvent.ACTION_MOVE: // 不论几个手指，只要触摸屏幕，都会走这个事件。
						// 其中setViewRotation方法需要两个手指的数据来计算弧度，因此要判断当前屏幕上响应了几个手指的触摸。
						if (rotationListen_ != null && event.getPointerCount() > 1) {
							setViewRotation(event);
						}
						break;
					}
				}
				return true;
			}
		});
		// 遍历他的所有子控件，为其设置监听
		if (c.realView_ instanceof ViewGroup) {
			int size = ((ViewGroup) (c.realView_)).getChildCount();
			for (int i = 0; i < size; i++) {
				setRotation(c.getComponent(((ViewGroup) (c.realView_))
						.getChildAt(i)));
			}
		}
	}

	/**
	 * 设置view的滑动方向
	 * 
	 * @param e1
	 *            down时的motionevent事件
	 * @param e2
	 *            move后的motionevent事件
	 */
	private void setViewGestureOrientation(MotionEvent e1, MotionEvent e2) {
		if (swipeListener_ == null) {
			return;
		}
		// 滑动方向
		String gestureOrientation = null;

		float x = e2.getX() - e1.getX();
		float y = e2.getY() - e1.getY();
		// 限制必须得划过屏幕的10px才能算划过
		float x_limit = 10;
		float y_limit = 10;
		float x_abs = Math.abs(x);
		float y_abs = Math.abs(y);
		if (x_abs >= y_abs) {
			// gesture left or right
			if (x > x_limit || x < -x_limit) {
				if (x > 0) {
					// right
					gestureOrientation = "right";
				} else if (x <= 0) {
					// left
					gestureOrientation = "left";
				}
			}
		} else {
			// gesture down or up
			if (y > y_limit || y < -y_limit) {
				if (y > 0) {
					// down
					gestureOrientation = "down";
				} else if (y <= 0) {
					// up
					gestureOrientation = "up";
				}
			}
		}

		if (gestureOrientation != null) {
			try {
				// 创建一个table
				Component.LUASTATE.newTable();
				LuaObject table = Component.LUASTATE.getLuaObject(-1);
				Component.LUASTATE.pop(1);
				// 将约定的固有参数压入表中
				table.push();
				Component.LUASTATE.pushObjectValue("direction");
				Component.LUASTATE.pushObjectValue(gestureOrientation);
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pop(1);
				swipeListener_.call(new Object[] { table });
			} catch (LuaException e) {
				Utils.printException(e);
			}
		}
	}

	/**
	 * 设置view的滑动弧度
	 * 
	 * @param e1
	 *            down时的motionevent事件
	 * @param e2
	 *            move后的motionevent事件
	 */	
	private void setViewRotation(MotionEvent e) {
		istrac++;
		if (rotationListen_ == null || istrac < 10) {
			return;
		}
		istrac = 0;
		try {
			float rotation = getViewRotation(e.getX(0), e.getY(0), e.getX(1), e.getY(1));
			rotation = rotation - oldrotation;
			// 创建一个table
			Component.LUASTATE.newTable();
			LuaObject table = Component.LUASTATE.getLuaObject(-1);
			Component.LUASTATE.pop(1);
			// 将约定的固有参数压入表中
			table.push();
			Component.LUASTATE.pushObjectValue("rotation");
			Component.LUASTATE.pushObjectValue(rotation);
			Component.LUASTATE.setTable(-3);
			Component.LUASTATE.pop(1);
			rotationListen_.call(new Object[] { table });
		} catch (Exception le) {
			Utils.printException(le);
		}
	}

	/**
	 * 得到两点之间的弧度
	 * 
	 * @param px1
	 *            第一个点的x坐标
	 * @param py1
	 *            第一个点的y坐标
	 * @param px2
	 *            第二个点的x坐标
	 * @param py2
	 *            第二个点的y坐标
	 * @return
	 */
	private float getViewRotation(float px1, float py1, float px2, float py2) {
		// 得到两点x的距离
		float x = px2 - px1;
		// 得到两点y的距离
		float y = py2 - py1;
		// 算出斜边长
		float hypotenuse = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
		// 得到角度的余弦值
		float cosAngle = x / hypotenuse;
		// 通过反余弦定理获得其角度的弧度
		float radian = (float) Math.acos(cosAngle);
		// 通过滑动的方向判断弧度的正负
		if (py2 < py1) {
			radian = -radian;
		}
		return radian;
	}

	public class SimpleOnGestureListener extends
			GestureDetector.SimpleOnGestureListener {

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			if (tapListener_ == null) {
				return false;
			}
			try {
				// 创建一个table
				Component.LUASTATE.newTable();
				LuaObject table = Component.LUASTATE.getLuaObject(-1);
				Component.LUASTATE.pop(1);
				// 将约定的固有参数压入表中
				table.push();
				Component.LUASTATE.pushObjectValue("x");
				Component.LUASTATE.pushNumber(e.getX());
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pushObjectValue("y");
				Component.LUASTATE.pushNumber(e.getY());
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pushObjectValue("tag");
				// 单机返回1
				Component.LUASTATE.pushObjectValue(1);
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pop(1);
				tapListener_.call(new Object[] { table });
			} catch (LuaException e1) {
				Utils.printException(e1);
			}
			return super.onSingleTapUp(e);
		}

		@Override
		public void onLongPress(MotionEvent e) {
			if (longTapListener_ == null) {
				return;
			}
			try {
				// 创建一个table
				Component.LUASTATE.newTable();
				LuaObject table = Component.LUASTATE.getLuaObject(-1);
				Component.LUASTATE.pop(1);
				// 将约定的固有参数压入表中
				table.push();
				Component.LUASTATE.pushObjectValue("x");
				Component.LUASTATE.pushNumber(e.getRawX());
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pushObjectValue("y");
				Component.LUASTATE.pushNumber(e.getRawY());
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pop(1);
				longTapListener_.call(new Object[] { table });
			} catch (LuaException e1) {
				Utils.printException(e1);
			}
			super.onLongPress(e);
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			if (dragListener_ == null) {
				return false;
			}
			try {
				// 创建一个table
				Component.LUASTATE.newTable();
				LuaObject table = Component.LUASTATE.getLuaObject(-1);
				Component.LUASTATE.pop(1);
				// 将约定的固有参数压入表中
				table.push();
				Component.LUASTATE.pushObjectValue("x");
				Component.LUASTATE.pushNumber(-distanceX);
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pushObjectValue("y");
				Component.LUASTATE.pushNumber(-distanceY);
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pop(1);
				dragListener_.call(new Object[] { table });
			} catch (LuaException e) {
				Utils.printException(e);
			}
			return super.onScroll(e1, e2, distanceX, distanceY);
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			if (swipeListener_ != null) {
				setViewGestureOrientation(e1, e2);
			}
			return super.onFling(e1, e2, velocityX, velocityY);
		}

		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub
			super.onShowPress(e);
		}

		@Override
		public boolean onDown(MotionEvent e) {
			// TODO Auto-generated method stub
			return super.onDown(e);
		}

		@Override
		public boolean onDoubleTap(MotionEvent e) {
			if (tapListener_ == null) {
				return false;
			}
			try {
				// 创建一个table
				Component.LUASTATE.newTable();
				LuaObject table = Component.LUASTATE.getLuaObject(-1);
				Component.LUASTATE.pop(1);
				// 将约定的固有参数压入表中
				table.push();
				Component.LUASTATE.pushObjectValue("x");
				Component.LUASTATE.pushNumber(e.getX());
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pushObjectValue("y");
				Component.LUASTATE.pushNumber(e.getY());
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pushObjectValue("tag");
				// 双击返回2
				Component.LUASTATE.pushObjectValue(2);
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pop(1);
				tapListener_.call(new Object[] { table });
			} catch (LuaException e1) {
				Utils.printException(e1);
			}
			return super.onDoubleTap(e);
		}

		@Override
		public boolean onDoubleTapEvent(MotionEvent e) {
			// TODO Auto-generated method stub
			return super.onDoubleTapEvent(e);
		}

		@Override
		public boolean onSingleTapConfirmed(MotionEvent e) {
			// TODO Auto-generated method stub
			return super.onSingleTapConfirmed(e);
		}

	}

	public class ScaleGestureListener implements
			ScaleGestureDetector.OnScaleGestureListener {

		@Override
		public boolean onScale(ScaleGestureDetector detector) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean onScaleBegin(ScaleGestureDetector detector) {
			// TODO Auto-generated method stub
			return true;
		}

		@Override
		public void onScaleEnd(ScaleGestureDetector detector) {
			float scaleFactor = detector.getScaleFactor();
			if (scaleListener_ == null || scaleFactor == 0) {
				return;
			}
			try {
				// 创建一个table
				Component.LUASTATE.newTable();
				LuaObject table = Component.LUASTATE.getLuaObject(-1);
				Component.LUASTATE.pop(1);
				// 将约定的固有参数压入表中
				table.push();
				Component.LUASTATE.pushObjectValue("scale");
				Component.LUASTATE.pushObjectValue(scaleFactor);
				Component.LUASTATE.setTable(-3);
				Component.LUASTATE.pop(1);
				scaleListener_.call(new Object[] { table });
			} catch (LuaException e) {
				Utils.printException(e);
			}
		}

	}
	
	/**
	 * 判断设备是否支持多点触摸。
	 */
	private boolean isSupportMultiTouch(){
		PackageManager pm = ConfigManager.currentView_.getPackageManager();
		if(pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)){ // 支持两点或多点触摸。
			return true;
		} else if(pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)){ // 支持基本的两点触摸。
			return true;
		}
		return false;
	}

}
